﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Duality;
using Duality.Components;
using Duality.Components.Renderers;
using Duality.Components.Physics;

using OpenTK;

using MagicPrototype.MagicSystem;

namespace MagicPrototype.TestStuff
{
	[Serializable]
	[RequiredComponent(typeof(RigidBody))]
	[RequiredComponent(typeof(AnimSpriteRenderer))]
    public class Character : Component, ICmpUpdatable, ISpellHost
    {
		private	float	health				= 100.0f;
		private	float	mana				= 100.0f;
		private	Vector2	targetVel			= Vector2.Zero;
		private	float	targetDir			= 0.0f;
		private	int		spriteSheetIndex	= 0;
		private	int		spriteSheetOffset	= 0;
		private	float	spriteSheetBaseDuration	= 1.0f;
		[NonSerialized]
		private	float	damageReaction		= 0.0f;
		[NonSerialized]
		private	SoundInstance	damageSound	= null;


		public float Health
		{
			get { return this.health; }
			set { this.health = value; }
		}
		public float Mana
		{
			get { return this.mana; }
			set { this.mana = value; }
		}
		public float DamageReaction
		{
			get { return this.damageReaction; }
		}
		public Vector2 TargetVel
		{
			get { return this.targetVel; }
			set { this.targetVel = value; }
		}
		public float TargetDir
		{
			get { return this.targetDir; }
			set { this.targetDir = value; }
		}
		public int SpriteSheetIndex
		{
			get { return this.spriteSheetIndex; }
			set { this.spriteSheetIndex = value; }
		}
		public int SpriteSheetOffset
		{
			get { return this.spriteSheetOffset; }
			set { this.spriteSheetOffset = value; }
		}
		public float SpriteSheetBaseDuration
		{
			get { return this.spriteSheetBaseDuration; }
			set { this.spriteSheetBaseDuration = value; }
		}

		private AnimSpriteRenderer Sprite
		{
			get { return this.GameObj.GetComponent<AnimSpriteRenderer>(); }
		}


		public void DoDamage(float damage)
		{
			this.health -= damage;
			this.health = MathF.Clamp(this.health, 0.0f, 100.0f);
			this.damageReaction += damage * 0.35f;
		}

		void ICmpUpdatable.OnUpdate()
		{
			Transform transform = this.GameObj.Transform;
			RigidBody body = this.GameObj.RigidBody;
			AnimSpriteRenderer sprite = this.Sprite;

			this.mana = MathF.Clamp(this.mana + Time.TimeMult * 0.01f, 0.0f, 100.0f);
			this.health = MathF.Clamp(this.health + Time.TimeMult * 0.001f, 0.0f, 100.0f);
			this.damageReaction -= MathF.Clamp(this.damageReaction * Time.TimeMult * 0.1f, 0.0f, 1.0f);

			if (this.damageReaction > 0.005f)
			{
				if (this.damageSound == null) this.damageSound = DualityApp.Sound.PlaySound3D(GameRes.Data.Sounds.MaleScreamPain_Sound, this.GameObj);
				this.damageSound.Volume = MathF.Clamp(0.05f + this.damageReaction, 0.0f, 1.0f);
			}
			else
			{
				if (this.damageSound != null) this.damageSound.FadeOut(0.5f);
			}
			if (this.damageSound != null && this.damageSound.Disposed) this.damageSound = null;

			body.ApplyWorldForce((targetVel - body.LinearVelocity) * 0.1f * body.Mass);

			bool isMoving = targetVel.Length > 0.001f;
			if (isMoving) sprite.AnimDuration = this.spriteSheetBaseDuration / (targetVel.Length / 5.0f);
			sprite.AnimPaused = !isMoving;

			if (MathF.CircularDist(this.targetDir, 0.0f) <= MathF.RadAngle45)
				sprite.AnimFirstFrame = this.spriteSheetIndex + this.spriteSheetOffset * 0;
			else if (MathF.CircularDist(this.targetDir, MathF.RadAngle90) <= MathF.RadAngle45)
				sprite.AnimFirstFrame = this.spriteSheetIndex + this.spriteSheetOffset * 1;
			else if (MathF.CircularDist(this.targetDir, MathF.RadAngle270) <= MathF.RadAngle45)
				sprite.AnimFirstFrame = this.spriteSheetIndex + this.spriteSheetOffset * 3;
			else
				sprite.AnimFirstFrame = this.spriteSheetIndex + this.spriteSheetOffset * 2;
		}

		Vector2 ISpellHost.Pos
		{
			get { return this.GameObj.Transform.Pos.Xy; }
		}
		float ISpellHost.DrainEnergy(float required)
		{
			float usedEnergy = MathF.Min(this.mana * 100.0f, required);
			this.mana -= usedEnergy * 0.01f;
			return usedEnergy;
		}
	}
}
